package cn.car.service.config;

import cn.car.domains.enums.EmissionStandardEnum;
import cn.car.mapper.SystemConfigMapper;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import jakarta.annotation.Resource;
import lombok.Getter;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
@Getter
public class SystemConfig {


    @Resource
    private SystemConfigMapper systemConfigMapper;

    private final Cache<String, String> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(5, java.util.concurrent.TimeUnit.MINUTES)
            .maximumSize(1000)
            .build();


    /**
     * 企业配置
     */
    private final ISystemConfigItem<String> enterpriseName = this.createItem("enterprise.name", "xxx有限公司");

    /**
     * 过滤车牌
     */
    private final ISystemConfigItem<String> ignorePlateNumber = this.createItem("ignore.plateNumber", ".*挂.*");

    /**
     * 辅助摄像头ip转换
     */
    private final ISystemConfigItem<Map<String, String>> detectedCameraMap = this.createItem("detected.camera.map", new HashMap<>());

    /**
     * 摄像头ip转换
     */
    private final ISystemConfigItem<Map<String, String>> bindCameraMap = this.createItem("bind.camera.map", new HashMap<>());


    /**
     * jwt密钥SECRET_KEY
     */
    private final ISystemConfigItem<String> jwtSecretKey = this.createItem("jwt.secret.key", "your-256-bit-secret-key-1234567890");


    /**
     * 运输车辆最低排放标准
     */
    private final ISystemConfigItem<String> govEmissionStandardMin = this.createItem("gov.emission.standard", EmissionStandardEnum.CN_3.name());

    /**
     * 运输车辆管控进出场
     */
    private final ISystemConfigItem<String> vehicleEntryExitControlIn = this.createItem("vehicle.entry.exit.control.in", "ON");

    /**
     * 出厂是否需要校验
     */
    private final ISystemConfigItem<Boolean> exitPassValid = this.createItem("exit.pass.valid", false);

    private final ISystemConfigItem<String> govEndpoint = this.createItem("gov.platform.endpoint", "");

    /**
     * nvr配置
     */
    private final ISystemConfigItem<String> nvrType = this.createItem("nvr.type", "");

    /**
     * 政府对接相关
     */
    private final ISystemConfigItem<String> companyCode = this.createItem("company.code", "");


    private final ISystemConfigItem<String> govUsername = this.createItem("gov.platform.username", "");
    private final ISystemConfigItem<String> govPassword = this.createItem("gov.platform.password", "");

    private final ISystemConfigItem<Long> govPicBase64MaxBytes = this.createItem("gov.pic.base64.max.bytes", 2 * 1024 * 1024L);

    /**
     * 闸机配置
     */
    private final ISystemConfigItem<Integer> gateSignalOpen = this.createItem("gate.signal.open", 0);
    private final ISystemConfigItem<Integer> gateSignalSource = this.createItem("gate.signal.source", 0);

    private final ISystemConfigItem<Boolean> testStream = this.createItem("test.stream", true);

    private final ISystemConfigItem<String> nvrUserName = this.createItem("nvr.username", "admin");
    private final ISystemConfigItem<String> nvrPassWord = this.createItem("nvr.password", "tc123456");

    private final ISystemConfigItem<String> nvrUrl = this.createItem("nvr.url", "");
    private final ISystemConfigItem<String> liveNvrUrl = this.createItem("live.nvr.url", "");


    private final ISystemConfigItem<String> lastDetectBetweenTime = this.createItem("last.detect.between.time", "15");

    private final ISystemConfigItem<String> nvrCutVideoMaxInterval = this.createItem("nvr.cut.video.max.interval", "5");
    private final ISystemConfigItem<String> nvrCutVideoDelayTime = this.createItem("nvr.cut.video.delay.time", "0");

    private final ISystemConfigItem<Boolean> schemaSyncEnabled = this.createItem("schema.sync.enabled", false);
    private final ISystemConfigItem<Boolean> schemaSyncDryRun = this.createItem("schema.sync.dry.run", false);
    private final ISystemConfigItem<Boolean> schemaSyncAutoApply = this.createItem("schema.sync.auto.apply", true);
    private final ISystemConfigItem<Boolean> schemaSyncBackupBeforeApply  = this.createItem("schema.sync.backup.before.apply", true);

    @SuppressWarnings("unchecked")
    private <T> ISystemConfigItem<T> createItem(String key, T defVal) {
        if (defVal instanceof String) {
            return (ISystemConfigItem<T>) new ItemString(key, (String) defVal);
        } if (defVal instanceof Boolean) {
            return (ISystemConfigItem<T>) new ItemBoolean(key, (Boolean) defVal);
        } else {
            return (ISystemConfigItem<T>) new ItemJson(key, defVal.getClass(), defVal);
        }
    }

    private abstract static class AbsItem<T> implements ISystemConfigItem<T> {
        protected final String key;
        protected final T defVal;

        AbsItem(String key, T defVal) {
            this.key = key;
            this.defVal = defVal;
        }
    }


    private class ItemString extends AbsItem<String> {
        private ItemString(String key, String defVal) {
            super(key, defVal);
        }


        @Override
        public String get(Class<String> clazz) {
            String item = cache.getIfPresent(key);

            if (item != null) {
                return item;
            }

            String value = systemConfigMapper.getString(key);
            if (StrUtil.isEmpty(value)) {
                cache.put(key, defVal);
                return defVal;
            }

            cache.put(key, value);
            return value;
        }

        @Override
        public void set(String value) {
            systemConfigMapper.putString(key, value);
        }
    }


    private class ItemJson<T> extends AbsItem<T> {
        private final Class<T> valClass;

        private ItemJson(String key, Class<T> valClass, T defVal) {
            super(key, defVal);
            this.valClass = valClass;
        }

        @Override
        public T get() {
            return this.get(valClass);
        }

        @Override
        public T get(Class<T> clazz) {
            String string = systemConfigMapper.getString(key);
            if (StrUtil.isEmpty(string)) {
                return defVal;
            }
            return JSONObject.parseObject(string, clazz);

        }

        @Override
        public void set(T value) {
            systemConfigMapper.putString(key, (String) value);
        }
    }


    private class ItemBoolean extends AbsItem<Boolean> {
        private ItemBoolean(String key, Boolean defVal) {
            super(key, defVal);
        }

        @Override
        public Boolean get(Class<Boolean> clazz) {
            String value = systemConfigMapper.getString(key);
            if (StrUtil.isEmpty(value)) {
                return defVal;
            }
            return Boolean.parseBoolean(value);
        }

        @Override
        public void set(Boolean value) {
            systemConfigMapper.putString(key, String.valueOf(value));
        }
    }






}
